
#include "lcd.h"
#include "console.h"
#include <stdio.h>
#include <string.h>
#include "def.h"
#include <stdlib.h>

#define DIGIPARANUM  10
#define DIGIPARASIZE  10

u32 time_count;
u32 time_count_tmp;
console_data ConsoleRingbuf;
const char *delim = " ";
u8 *tmp_ptr;
u8*  cammand_mane;
u16 Digitalpara[DIGIPARANUM];
u16 Digitalpara_num;
u8 *Stringpara[DIGIPARANUM];
u16 Stringpara_num;
u16 Para_num;
u8 console_exit_flag = 0;
u8 enter_flag = 0;
u8 upload_flash_flag = 0;
u8 start_app_flag = 0;
u8 xmodem_flag = 0;
u8 console_num = 0;
console_delay Console_Delay;
console_printf Console_Printf;

void Get_Ring_datalen(void);
void Get_Ring_readlen(void);
void Get_Ring_writelen(void);
void Exit_Console(void);
void Show_all_Cmd(void);
void uarttest(void);
void bmptest(void);
void lcdtest(void);
void reboot(void);
void test1(void);

application_struct application_list[20] ={
{"datalen","Get_Ring_datalen",Get_Ring_datalen},
{"readlen","Get_Ring_readlen",Get_Ring_readlen},
{"writelen","Get_Ring_writelen",Get_Ring_writelen},
{"exit","exit console",Exit_Console},
{"?","exit console",Show_all_Cmd},
{"lcd","lcd test",lcdtest},
{"uart","uart test",uarttest},
{"bmp","bmp test",bmptest},
{"reboot","reboot",reboot},
{"test1","test1",test1},
{"END","NULL",NULL},
};

void test1(void)
{
	Console_Printf("you sucess!!!\r\n");
}
void reboot(void)
{
	NVIC_SystemReset();
}


void lcdtest(void)
{
    if(Stringpara_num < 1){
        Console_Printf("para error\r\n");
        return;
    }
    ///LCD_Color_Fill(0,0,127,127,Getbmpdata(Stringpara[Stringpara_num -1]));

}

void bmptest(void)
{
    if(Stringpara_num < 1){
        Console_Printf("para error\r\n");
        return;
    }
    ///LCD_Color_Fill(0,0,127,127,Getbmpdata(Stringpara[Stringpara_num -1]));

}

void uarttest(void)
{
    u8 rt = 0;
}
void Show_all_Cmd(void)
{
    int i;
    for ( i = 0; i < console_num; i++)
    {
         Console_Printf("%s\r\n",application_list[i].name);
    }
    

}
void Exit_Console(void)
{
    Console_Printf("->");
    console_exit_flag = 1;
}
void Get_Ring_datalen(void)
{
    Console_Printf("datalen:%d\r\n",ConsoleRingbuf.datalen);
    //Console_Printf("sss\r\n");
}

void Get_Ring_readlen(void)
{
    Console_Printf("readlen:%d\r\n",ConsoleRingbuf.readlen);
}

void Get_Ring_writelen(void)
{
    Console_Printf("writelen:%d\r\n",ConsoleRingbuf.writelen);
}

void InitRintbuf(console_data *ConsoleRingbuf)
{
    int i;
    memset(ConsoleRingbuf->data,0,sizeof(u8)*MAXLEN);
    ConsoleRingbuf->datalen = 0;
    ConsoleRingbuf->readlen = 0;
    ConsoleRingbuf->writelen = 0;
    ConsoleRingbuf->status =bufok;
    cammand_mane = (u8 *)malloc(30 * sizeof(u8));

    tmp_ptr = (u8 *)malloc(DIGIPARASIZE * sizeof(u8));

    for(i=0;i<DIGIPARANUM;i++){
       Digitalpara[i] = 0;
    }
    for(i=0;i<DIGIPARANUM;i++){
       Stringpara[i] = (u8 *)malloc(DIGIPARASIZE * sizeof(u8));
        if(Stringpara[i] == NULL){
            Console_Printf("alloc failed\r\n");
            break;
        }
    }    
    
}


char *END_String = "END";
void Init_Console(console_delay p, console_printf pp)
{
    InitRintbuf(&ConsoleRingbuf);
    if (pp == NULL) {
    } else
    {
        Console_Printf = pp;
    } 
    

    if (p == NULL) {
        Console_Printf("func:%s\r\n",application_list[console_num].name);
    } else
    {
        Console_Delay = p;
    } 

    while (1)
    {
        if(strncmp(application_list[console_num].name,END_String,Get_ptrlen(END_String)) == 0){
					//Console_Printf("func:%s\r\n",application_list[console_num].name);
            break;
        }
        console_num++;
    }

}

u8 Add_char_toRingbuf(console_data *ConsoleRingbuf,u8 ch)
{
    if(ConsoleRingbuf == NULL){
        return noinit;
    }

    if((ConsoleRingbuf->writelen )> MAXLEN)
        ConsoleRingbuf->writelen = 0;

    if((ConsoleRingbuf->readlen == ConsoleRingbuf->writelen) && (ConsoleRingbuf->datalen > 0))
        return  full;

    ConsoleRingbuf->data[ConsoleRingbuf->writelen] = ch;
    ConsoleRingbuf->writelen++;
    ConsoleRingbuf->datalen++;
    return bufok;
}

u8 Add_buf_toRingbuf(console_data *ConsoleRingbuf,const u8* ch,u16 len)
{
    int i;
    if(ConsoleRingbuf == NULL){
        return noinit;
    }



    for(i=0;i<len;i++){
        if(ConsoleRingbuf->writelen > MAXLEN)
            ConsoleRingbuf->writelen = 0;

        if((ConsoleRingbuf->readlen == ConsoleRingbuf->writelen) && (ConsoleRingbuf->datalen > 0))
            return  full;
            ConsoleRingbuf->data[ConsoleRingbuf->writelen] = ch[i];
            ConsoleRingbuf->writelen++; 
            ConsoleRingbuf->datalen++;

        if((ConsoleRingbuf->readlen == ConsoleRingbuf->writelen) && (ConsoleRingbuf->datalen > 0))
            return  full;
    }
    return bufok;
}
u8 Get_char_fromRingbuf_last(console_data *ConsoleRingbuf,u8* ch)
{
    if(ConsoleRingbuf == NULL){
        return noinit;
    }

    if(ConsoleRingbuf->datalen == 0)
        return  empty;
    ConsoleRingbuf->writelen--;
    *ch = ConsoleRingbuf->data[ConsoleRingbuf->writelen];
    ConsoleRingbuf->datalen--;

    return bufok;
}

u8 Get_char_fromRingbuf(console_data *ConsoleRingbuf,u8* ch)
{
    if(ConsoleRingbuf == NULL){
        return noinit;
    }

    if((ConsoleRingbuf->readlen +1)> MAXLEN)
        ConsoleRingbuf->readlen = 0;

    if((ConsoleRingbuf->readlen == ConsoleRingbuf->writelen) && (ConsoleRingbuf->datalen == 0))
        return  empty;

    *ch = ConsoleRingbuf->data[ConsoleRingbuf->readlen];
    ConsoleRingbuf->readlen++;
    ConsoleRingbuf->datalen--;

    return bufok;
}

u8 Get_buf_fromRingbuf(console_data *ConsoleRingbuf,u8* ch,u16 len)
{
    int i;
    if(ConsoleRingbuf == NULL){
        return noinit;
    }

    for(i=0;i<len;i++){
        if(ConsoleRingbuf->readlen > MAXLEN)
            ConsoleRingbuf->readlen = 0;

        if((ConsoleRingbuf->readlen == ConsoleRingbuf->writelen) && (ConsoleRingbuf->datalen == 0)){
            Console_Printf("func:%s datalen:%d readlen:%d writelen:%d\r\n",__func__,ConsoleRingbuf->datalen, ConsoleRingbuf->readlen, ConsoleRingbuf->writelen);
            return  empty;
        }
            

        ch[i] = ConsoleRingbuf->data[ConsoleRingbuf->readlen];
        ConsoleRingbuf->readlen++; 
        ConsoleRingbuf->datalen--;           
    }
    return bufok;
}
void clear_para_list(void)
{
    u8 i;
    // for(i=0;i<Stringpara_num;i++)
    // {
    //    Digitalpara[i] = NULL;
    // }

    // for(i=0;i<Digitalpara_num;i++){
    //    Stringpara[i] = NULL;
    // }    
    
    Stringpara_num = 0;
    Digitalpara_num = 0;
    // cammand_mane = NULL;
}
u8 Get_ptrlen(char *data_ptr)
{
    u16 i;
        for(i=0;;i++){
            if(data_ptr[i] == '\0'){
                break;
            }
        }
        return i;
}
u8 String_copy(u8 *dest,u8 *src)
{
    if(src == NULL || dest == NULL){
        Console_Printf("func: %s ptr null\r\n", __func__);
        return 1;
    }

    while (*src != '\0')
    {
        *dest = *src;
        dest++;
        src++;
    }
    *dest ='\0';
}

u8 IsString(u8 *ptr)
{
    u8 index = 0;
    if(ptr == NULL){
        Console_Printf("func: %s ptr null\r\n", __func__);
        return OTHERS;
    }

    if (ptr[0] < '0' || ptr[0] > '9')
    {
        return STRING;
    }
    
    if (ptr[1] == 'x' || ptr[1] == 'X'){
        index = 2;
    }

    ptr += index;

    while (*ptr != '\0')
    {
        if (*ptr < '0' || *ptr > '9')
        {
            return STRING;
        }
				ptr++;
    }

    if (index == 0) {
        return DEC_NUMBER;
    }

    return HEX_NUMBER;
}

u8 Analysis_Cammand(void)
{
    u8 rt = 0;
    u8 ch = 0;
    u8 error = 0;
    u8 len = ConsoleRingbuf.datalen;
    u8 para_num = 0;
    Stringpara_num = 0;
    Digitalpara_num = 0;
    u8 *checkPtr = NULL;
    Para_num = 0;


    error = Get_buf_fromRingbuf(&ConsoleRingbuf,tmp_ptr,ConsoleRingbuf.datalen);
    tmp_ptr[len] = '\0';
    if(error == empty){
        Console_Printf("empty\r\n");
        return nothing;
    }

    if(len <= 0){
        return nothing;
    }else{
        if(tmp_ptr == NULL){
            Console_Printf("strcpy error");
            return nothing;
        }

        cammand_mane = (u8 *)strtok(tmp_ptr,delim);
        do{
            checkPtr = (u8 *)strtok(NULL,delim);
            if(checkPtr == NULL){
               break;
            }

            rt = IsString(checkPtr);
            if ( rt == STRING) {
                String_copy(Stringpara[Stringpara_num], checkPtr);
                // Console_Printf("%s\r\n", Stringpara[Stringpara_num]);
                Stringpara_num++;
            } else if (rt == DEC_NUMBER) {
                Digitalpara[Digitalpara_num] = atoi((const char *)checkPtr);
                // Console_Printf("%d\r\n", Digitalpara[Digitalpara_num]);
                Digitalpara_num++;
            } else if (rt == HEX_NUMBER){
                checkPtr += 2;
                Digitalpara[Digitalpara_num] = atoi((const char *)checkPtr);
                // Console_Printf("%d\r\n", Digitalpara[Digitalpara_num]);
                Digitalpara_num++;
            } else {
                Console_Printf("null\r\n");
            }
            
        }while(1);
        //Console_Printf("func:%s datalen:%d readlen:%d writelen:%d\r\n",__func__,ConsoleRingbuf.datalen, ConsoleRingbuf.readlen, ConsoleRingbuf.writelen);
        //Console_Printf("func:%s cammand_mane:%s Stringpara:%s\r\n",__func__,cammand_mane,Stringpara[0]);
        Console_Printf("\r\n");
        Para_num = Digitalpara_num + Stringpara_num;
        return enter;
    }

    return nothing;
}


u8 Deal_keyboard(u8 data)
{
    u8 ch;
    int error = 0;
    if (1){//如果有按键按下，则_kbhit()函数返回真
        ch = data;
        if (ch != 8){
					if (ch != '\r' && ch != '\n')
						Console_Printf("%c",ch);
        }
        if(((ch > 47)&&(ch < 58)) || ((ch >64)&&(ch<106)) || 
          ((ch >96) && (ch < 126)) ||((ch >31)&&(ch < 81)) ){
            error = Add_char_toRingbuf(&ConsoleRingbuf,ch); 
        }
        
        if(error == bufok){
           
        }else if(error == empty){
            Console_Printf("empty\r\n"); 
        }else if(error == full){
            Console_Printf("full\r\n");
        }else if(error == noinit){
            Console_Printf("noinit\r\n");
        }

        if(ch == '\r' || ch == '\n'){
            enter_flag = 1;
            Console_Printf("\r\n");
            return enter;
        }
        if(ch == 8){//删除.
            if (ConsoleRingbuf.datalen == 0) {
                return nothing;
            }
			Console_Printf("%c",ch);
            Console_Printf(" ");
			Console_Printf("%c",ch);
            Get_char_fromRingbuf_last(&ConsoleRingbuf,&ch);
            //Console_Printf("Get:datalen:%d,writelen:%d,readlen:%d\r\n",ConsoleRingbuf.datalen,ConsoleRingbuf.writelen,ConsoleRingbuf.readlen); 
        }

    }
    return nothing;
}

u8 Check_iput(void)
{
    if(enter_flag == 1){
            enter_flag = 0;
            return enter;
    }
    return nothing;
}


u8 Waitforinput()
{
    u8 ch = 0;
    u16 count = 0;
    u16 count1 = 0;
    while(1)
    {

        ch = Check_iput();
        if(ch){
           return 1; 
        }
        else{
               count++;
               if(count > 200){
                    count = 0;
                    count1++;
                    Console_Printf(".");  
               }
               Console_Delay(1);
        }
        if(count1 >20){
            return nothing;
        }
    }
    return nothing;
}


void Console_main(void)
{
    int i;
    int len = 0;
    int rt = 0;
    u8 func_flag = 0;
    console_exit_flag = 0;
    Console_Printf("func:%s\r\n",__func__);
    rt = Waitforinput();
    if(rt == nothing){
        return ;
    }
    Console_Printf("\r\n");
    Console_Printf("stm32->");
    while(1){
    
        rt = Check_iput();
        if(rt <= 0){
            //Console_Printf("no input");
            continue;
        }

        len = Analysis_Cammand();
        if(len <= 0){
           // Console_Printf("len<=0");
            clear_para_list();
            Console_Printf("nofind the cammand");
            Console_Printf("\r\n");
            Console_Printf("stm32->");
            continue;
        }
        //Console_Printf("%d %d\r\n",Get_ptrlen(cammand_mane),strlen(application_list[1].name));
        for(i = 0; i < console_num; i++){
            if(strncmp(application_list[i].name,cammand_mane,Get_ptrlen(application_list[i].name)) == 0){
           
                    application_list[i].func();
                    func_flag = 1;
                    Console_Printf("\r\n");
                    Console_Printf("stm32->");
                    break;
            }           
        }

        if(func_flag == 0){
             //Console_Printf("func_flag == 0");
             clear_para_list();
             Console_Printf("nofind the cammand");
             Console_Printf("\r\n");
             Console_Printf("->");
        }
        func_flag = 0;
        clear_para_list();

        
        if(console_exit_flag == 1){
            console_exit_flag = 0;
            break;
        }

    }
    
}

u8 Deal_ConsoleMian(void)
{
    return Check_iput(); 
}